#include "feature.h"
#include "operators.h"
#include "constant.h"

FeatureSpecName::~FeatureSpecName()
{
	if (isOwningData())
	{
		delete m_name;
	}
}

void FeatureSpecName::write(GraphStream * s)
{
  this->accept(s);
}

std::string getNamesList(ListNode<FeatureSpecName> * specnames)
{
 std::string names;
 const std::vector<FeatureSpecName *> & specs=specnames->vector();
 for(unsigned int i=0;i<specs.size();i++)
 {
  if (specs[i]->spec()==FDT_FROZEN)
			names+="Frozen ";
  names+=specs[i]->name();
  if (specs[i]->alias())
  {
	  names+=" alias ";
	  names+=*( specs[i]->alias() );
	  if ( *(specs[i]->alias()) == "\\\\" )
		  names+="\\\\";
  }
  if (i!=specs.size()-1)
		names+=",\\n";
 }
 return names;
}


void FeatureDeclaration::setExplicitValue(AbstractNode * explicitvalue)
{
	delete m_behaviour;
    m_behaviour=new MethodDeclaration();
	m_routine=createExplicitValueRoutine(explicitvalue);
}
void FeatureDeclaration::makeDeferredMethod()
{
	delete m_behaviour;
	m_behaviour=new DeferredMethodDeclaration();
	m_routine=NULL;
}
void FeatureDeclaration::makeEffective(EntityList * local,Compound * routine)
{
	delete m_behaviour;
	m_behaviour=new MethodDeclaration();
	m_routine=routine;
    m_local_vars=local;
}
FeatureDeclaration::FeatureDeclaration(const YYLTYPE & pos,
									   ListNode<FeatureSpecName> * names,
		                               EntityList * formalargs,
									   ClassTypeNode * type) : AbstractNode(pos)
{
		  m_behaviour=new DeferredMethodDeclaration();
		  m_formal_args=formalargs;
		  m_return_type=type;
		  m_local_vars=NULL;
		  m_specnames=names;
		  m_routine=NULL;
}

FeatureDeclaration::FeatureDeclaration(const YYLTYPE & pos,ListNode<FeatureSpecName> * names,
		                               EntityList * formalargs,ClassTypeNode * type,
									   EntityList * localvars,Compound * routine) : AbstractNode(pos)
{
		  m_behaviour=new MethodDeclaration();
		  m_formal_args=formalargs;
		  m_return_type=type;
		  m_local_vars=localvars;
		  m_specnames=names;
		  m_routine=routine;
}
std::string FeatureDeclaration::getNamesList()
{
 return ::getNamesList(m_specnames);
}

FeatureDeclaration::~FeatureDeclaration()
{
	if (this->isOwningData())
	{
		delete m_formal_args;
		delete m_return_type;
		delete m_local_vars;
		delete m_routine;
		delete m_specnames;
	}
	delete m_behaviour;
}

void  FeatureDeclaration::write(GraphStream * s)
{
	this->accept(s);
	this->m_behaviour->write(this,s);
}

void  FeatureDeclaration::write(AbstractNode * node,const std::string & mark,GraphStream * s)
{
 if (node)
 {
	 node->write(s);
	 fprintf(s->stream,"\tnode_%d -> node_%d [label=\"%s\"]\n",number(),node->number(),mark.c_str());	
 }
}
void DeferredMethodDeclaration::write(FeatureDeclaration *decl, GraphStream *s)
{
	fprintf(s->stream,"\tnode_%d [label=\"(%d,%d) \\nDeferred methods: \\n%s\" shape=\"rectangle\"]\n",decl->number(),decl->line(),decl->position(),decl->getNamesList().c_str());
	decl->write(decl->m_formal_args,"formal arguments",s);
    decl->write(decl->m_return_type,"return type",s);
}

void MethodDeclaration::write(FeatureDeclaration *decl, GraphStream *s)
{
 std::string str=decl->getNamesList();
 fprintf(s->stream,"\tnode_%d [label=\"(%d,%d) \\n Methods: \\n%s\" shape=\"rectangle\"]\n",decl->number(),decl->line(),decl->position(),str.c_str());
 decl->write(decl->m_formal_args,"formal arguments",s);
 decl->write(decl->m_return_type,"return type",s);
 decl->write(decl->m_local_vars,"local variables",s);
 decl->write(decl->m_routine,"routine",s);
}
void FieldDeclaration::write(FeatureDeclaration *decl, GraphStream *s)
{
 fprintf(s->stream,"\tnode_%d [label=\"(%d,%d) \\n Fields: \\n%s\" shape=\"rectangle\"]\n",decl->number(),decl->line(),decl->position(),decl->getNamesList().c_str());
 decl->write(decl->m_return_type,"type",s);
}

void  FeatureGroup::write(GraphStream * s)
{
	this->accept(s);
	fprintf(s->stream,"\tnode_%d [label=\"(%d,%d)\\nFeature Group\" shape=\"rectangle\"]\n",this->number(),this->line(),this->position());
	if (m_clients)
	{
	  m_clients->write(s);
	  fprintf(s->stream,"\tnode_%d -> node_%d [label=\"clients\"]\n",this->number(),m_clients->number());
	}
	m_features->write(s);
	fprintf(s->stream,"\tnode_%d -> node_%d [label=\"features\"]\n",this->number(),m_features->number());
}

FeatureCommand::~FeatureCommand()
{
}

Compound * createExplicitValueRoutine(AbstractNode * node)
{
	YYLTYPE pos=make_pos(node->line(),node->position());
	Compound * compound=CREATE_LIST(pos,AbstractNode);
	OperatorNode * call=new OperatorNode(pos,
		                         new IdentifierNode(pos,push_string("RESULT")),
								 node,":=");
	compound->add(call);
	return compound;
}
